{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "hd0pcV-Y6uF0",
        "outputId": "fed99bc3-2bed-42fe-c763-3315a18b8235"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "2025-09-17 09:05:20,496 - pipeline_logger - INFO - Pipeline started for: sample_equation.png\n",
            "INFO:pipeline_logger:Pipeline started for: sample_equation.png\n",
            "2025-09-17 09:05:20,499 - pipeline_logger - INFO - Timing started for: wrapper\n",
            "INFO:pipeline_logger:Timing started for: wrapper\n",
            "2025-09-17 09:05:20,503 - pipeline_logger - INFO - Entering: ocr_extract | Args: ('sample_equation.png',) | Kwargs: {}\n",
            "INFO:pipeline_logger:Entering: ocr_extract | Args: ('sample_equation.png',) | Kwargs: {}\n",
            "2025-09-17 09:05:20,506 - pipeline_logger - INFO - Exiting: ocr_extract | Result: E = mc^2\n",
            "INFO:pipeline_logger:Exiting: ocr_extract | Result: E = mc^2\n",
            "2025-09-17 09:05:20,507 - pipeline_logger - INFO - Timing ended for: wrapper | Duration: 8.00 ms\n",
            "INFO:pipeline_logger:Timing ended for: wrapper | Duration: 8.00 ms\n",
            "2025-09-17 09:05:20,511 - pipeline_logger - INFO - Timing started for: wrapper\n",
            "INFO:pipeline_logger:Timing started for: wrapper\n",
            "2025-09-17 09:05:20,512 - pipeline_logger - INFO - Entering: wrapper | Args: ('E = mc^2',) | Kwargs: {}\n",
            "INFO:pipeline_logger:Entering: wrapper | Args: ('E = mc^2',) | Kwargs: {}\n",
            "2025-09-17 09:05:20,513 - pipeline_logger - INFO - Cache miss for symbolic_reasoning with args ('E = mc^2',)\n",
            "INFO:pipeline_logger:Cache miss for symbolic_reasoning with args ('E = mc^2',)\n",
            "2025-09-17 09:05:20,516 - pipeline_logger - INFO - Exiting: wrapper | Result: {'expression': 'E = mc^2', 'parsed': 'Energy equals mass times speed of light squared'}\n",
            "INFO:pipeline_logger:Exiting: wrapper | Result: {'expression': 'E = mc^2', 'parsed': 'Energy equals mass times speed of light squared'}\n",
            "2025-09-17 09:05:20,517 - pipeline_logger - INFO - Timing ended for: wrapper | Duration: 6.82 ms\n",
            "INFO:pipeline_logger:Timing ended for: wrapper | Duration: 6.82 ms\n",
            "2025-09-17 09:05:20,521 - pipeline_logger - INFO - Pipeline completed. Final result: {'expression': 'E = mc^2', 'parsed': 'Energy equals mass times speed of light squared'}\n",
            "INFO:pipeline_logger:Pipeline completed. Final result: {'expression': 'E = mc^2', 'parsed': 'Energy equals mass times speed of light squared'}\n"
          ]
        }
      ],
      "source": [
        "#Under the help of Microsoft Copilot\n",
        "import logging\n",
        "import time\n",
        "from cachetools import TTLCache\n",
        "\n",
        "# -------------------- Logging Setup --------------------\n",
        "def setup_logger(name='pipeline_logger', level=logging.INFO, log_file='pipeline.log'):\n",
        "    logger = logging.getLogger(name)\n",
        "    logger.setLevel(level)\n",
        "\n",
        "    # File handler\n",
        "    fh = logging.FileHandler(log_file)\n",
        "    fh.setLevel(level)\n",
        "\n",
        "    # Console handler\n",
        "    ch = logging.StreamHandler()\n",
        "    ch.setLevel(logging.DEBUG)\n",
        "\n",
        "    # Formatter\n",
        "    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n",
        "    fh.setFormatter(formatter)\n",
        "    ch.setFormatter(formatter)\n",
        "\n",
        "    # Add handlers\n",
        "    logger.addHandler(fh)\n",
        "    logger.addHandler(ch)\n",
        "\n",
        "    return logger\n",
        "\n",
        "logger = setup_logger()\n",
        "\n",
        "# -------------------- Decorators --------------------\n",
        "def log_function(func):\n",
        "    def wrapper(*args, **kwargs):\n",
        "        logger.info(f\"Entering: {func.__name__} | Args: {args} | Kwargs: {kwargs}\")\n",
        "        try:\n",
        "            result = func(*args, **kwargs)\n",
        "            logger.info(f\"Exiting: {func.__name__} | Result: {result}\")\n",
        "            return result\n",
        "        except Exception as e:\n",
        "            logger.error(f\"Error in {func.__name__}: {e}\")\n",
        "            return None\n",
        "    return wrapper\n",
        "\n",
        "cache = TTLCache(maxsize=100, ttl=600)\n",
        "\n",
        "def cache_function(func):\n",
        "    def wrapper(*args):\n",
        "        if args in cache:\n",
        "            logger.info(f\"Cache hit for {func.__name__} with args {args}\")\n",
        "            return cache[args]\n",
        "        else:\n",
        "            logger.info(f\"Cache miss for {func.__name__} with args {args}\")\n",
        "            result = func(*args)\n",
        "            cache[args] = result\n",
        "            return result\n",
        "    return wrapper\n",
        "\n",
        "def time_function(func):\n",
        "    def wrapper(*args, **kwargs):\n",
        "        start_time = time.time()\n",
        "        logger.info(f\"Timing started for: {func.__name__}\")\n",
        "\n",
        "        result = func(*args, **kwargs)\n",
        "\n",
        "        end_time = time.time()\n",
        "        elapsed_ms = (end_time - start_time) * 1000\n",
        "        logger.info(f\"Timing ended for: {func.__name__} | Duration: {elapsed_ms:.2f} ms\")\n",
        "\n",
        "        return result\n",
        "    return wrapper\n",
        "\n",
        "# -------------------- OCR Module --------------------\n",
        "@time_function\n",
        "@log_function\n",
        "def ocr_extract(image_path):\n",
        "    # Simulated OCR logic (replace with real OCR engine)\n",
        "    return \"E = mc^2\"\n",
        "\n",
        "# -------------------- Reasoning Module --------------------\n",
        "@time_function\n",
        "@log_function\n",
        "@cache_function\n",
        "def symbolic_reasoning(text):\n",
        "    # Simulated symbolic parsing (replace with SymPy or Wolfram)\n",
        "    return {\n",
        "        \"expression\": text,\n",
        "        \"parsed\": \"Energy equals mass times speed of light squared\"\n",
        "    }\n",
        "\n",
        "# -------------------- Pipeline Controller --------------------\n",
        "def run_pipeline(image_path):\n",
        "    logger.info(f\"Pipeline started for: {image_path}\")\n",
        "\n",
        "    text = ocr_extract(image_path)\n",
        "    if not text:\n",
        "        logger.warning(\"OCR failed or returned empty.\")\n",
        "        return None\n",
        "\n",
        "    result = symbolic_reasoning(text)\n",
        "    logger.info(f\"Pipeline completed. Final result: {result}\")\n",
        "    return result\n",
        "\n",
        "# -------------------- Example Execution --------------------\n",
        "if __name__ == \"__main__\":\n",
        "    image_path = \"sample_equation.png\"\n",
        "    output = run_pipeline(image_path)\n"
      ]
    }
  ]
}